Shader "Builtin-YoFi/VFX/ModelOutline"
{
    Properties
    {
        
        _MainTex("MainTex", 2D) = "white" {}
        [Toggle]_MainTexScreenUV("_MainTexScreenUV", Float) = 0
        [Toggle]_MainTexClamp("MainTexClamp", Float) = 0
        [HDR]_MainColor("MainColor", Color) = (1,1,1,1)
        _MainTexUSpeed("MainTexUSpeed", Float) = 0
        _MainTexVSpeed("MainTexVSpeed", Float) = 0
        
        _ColorTex("ColorTex", 2D) = "white" {}
        [Toggle]_ColorTexScreenUV("_ColorTexScreenUV", Float) = 0
        _ColorTexUSpeed("ColorTexUSpeed", Float) = 0
        _ColorTexVSpeed("ColorTexVSpeed", Float) = 0
        _ColorTexIntensity("ColorTexIntensity", Range(0,1)) = 1
        


        [HDR]_FnlColor("FnlColor", Color) = (1,1,1,1)
        _FnlScale("FnlScale", Range( 0 , 2)) = 0
        _FnlPower("FnlPower", Range( 1 , 10)) = 1





        
        [Toggle]_CBLocalBanBool("单独关闭Bloom",float) = 0
        _CBLocalThreshold("CB Threshhold",range(0.0,1.0)) = 1
        _CBLocalColor("CB Color",Color) = (1,1,1,1)
        _CBLocalLight("CB 亮度",float) = 1
        
        [Toggle]_IsClipGround("是否有地面[8h6H,Y = 0]",float) = 0
        _IsClipGroundBlur("地面接缝过度[8h6h]",float) = 0.5


        
        _OutlineWidth("_OutlineWidth", float) = 0.3
        _ZCorrection("_ZCorrection", float) = 0.3
        _OutlineTint("_OutlineTint", color) = (1,1,1,1)
    }

    SubShader
    {
        Tags 
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }
        AlphaToMask Off

        HLSLINCLUDE
             
            
            #include "UnityShaderVariables.cginc"
		    #include "UnityCG.cginc"
            #include "HLSLSupport.cginc"

            


            
        CBUFFER_START(UnityPerMaterial)


            float4 _ColorTex_ST;
            float _ColorTexIntensity;
            float _ColorTexUSpeed;
            float _ColorTexVSpeed;

            float _MainTexScreenUV;
            float _ColorTexScreenUV;
            
            float4 _MainTex_ST;
            float4 _MainColor;


            float _CustomMainTex;
            float _MainTexVSpeed;
            float _MainTexUSpeed;
            float _MainTexClamp;


            float4 _FnlColor;

            float _FnlScale;
            float _FnlPower;




            
            

            float _IsClipGround, _IsClipGroundBlur;

            float _CBLocalThreshold;
            float4 _CBLocalColor;
            float _CBLocalLight;
            half _CBGlobalBool;
            half _CBLocalBanBool;

            float _OutlineWidth;
            float4 _OutlineTint;
            float _ZCorrection;

        CBUFFER_END
            
            sampler2D _MainTex;
            sampler2D _ColorTex;


            inline float4 BloomOutfrag(float4 col){
                if(_CBLocalBanBool == 1){
                    return col;
                }
                if(_CBGlobalBool == 1){
                    float cc = dot(col.rgb, float3(0.2126729f,  0.7151522f, 0.0721750f)) ;
                    half bcol = smoothstep(1.0 - max(0,_CBLocalThreshold), 1.0 , cc);
                    half3 nc =  bcol;
                    half3 value = nc * _CBLocalLight * _CBLocalColor.rgb;
                    value *= col.rgb * col.a;
                    col.rgb += value; 
                    return col;
                }
                else{
                    return col;
                }
            }
            inline float dt_ClipInWorldY(float worldposY)
            {
	            if(_IsClipGround > 0){		
    	            return smoothstep(0, _IsClipGroundBlur,worldposY);
	            }else{
		            return 1.0;
	            }
                
            }
            inline float4 LastExportColor(float4 fragcolor, float worldPos_y)
            {
	            fragcolor = saturate(fragcolor);
	            fragcolor.a *= dt_ClipInWorldY(worldPos_y);
	            return BloomOutfrag(fragcolor);
            } 

            inline float UnityGet2DClipping(in float2 position, in float4 clipRect)
            {
                float2 inside = step(clipRect.xy, position.xy) * step(position.xy, clipRect.zw);
                return inside.x * inside.y;
            }


        ENDHLSL

         Pass
        {
            Name "ModelForward"
            Tags 
            { 
                "RenderType"="Transparent" 
                "LightMode" = "ForwardBase"
                "Queue"="Transparent"
            }
            Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha
            ZWrite On
            ZTest LEqual
            
            ColorMask RGBA
            Cull Back
            
            
            HLSLPROGRAM
            
            //#include "Assets/AssetsPackage/Shaders/Common/Included/YFEffectBase.cginc"
            //#include "Assets/AssetsPackage/Shaders/Common/Included/YoFi_FXShow_Base.cginc"
            #pragma vertex vert
            #pragma fragment frag


            


           
            
            

            struct VertexInput
            {
                float4 vertex    : POSITION;

                float3 normal    : NORMAL;

                float4 color      : COLOR;
                float4 texcoord  : TEXCOORD0;
                float4 texcoord1 : TEXCOORD1;

                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct VertexOutput
            {
                float4 positionHCS : SV_POSITION;
                float4 color       : COLOR;
                float4 uv          : TEXCOORD0;

                float3 positionWS  : TEXCOORD3;

                float4 normalWS    : TEXCOORD5;

            // #ifdef _FDEPTH_ON
            //     float4 positionSS  : TEXCOORD6;
            // #endif
                float3 positionOS  : TEXCOORD7;
                float4 positionSS : TEXCOORD8;
                UNITY_VERTEX_INPUT_INSTANCE_ID
                UNITY_VERTEX_OUTPUT_STEREO
            };


            VertexOutput vert(VertexInput v)
            {
                VertexOutput OUT = (VertexOutput)0;
                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_TRANSFER_INSTANCE_ID(v, OUT);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
                

                OUT.normalWS.xyz = normalize(mul(float4(v.normal,0.0),unity_WorldToObject).xyz);
                OUT.normalWS.w = 0;			

                OUT.color = v.color;
                OUT.uv.xy = v.texcoord.xy;
                OUT.uv.zw = 0;

                float3 positionWS = mul(UNITY_MATRIX_M,float4(v.vertex.xyz, 1.0));
                float4 positionHCS = mul(UNITY_MATRIX_VP,float4(positionWS, 1.0));
                OUT.positionSS = ComputeScreenPos(positionHCS);
                

                OUT.positionWS = positionWS;
                OUT.positionHCS = positionHCS;
                OUT.positionOS = v.vertex.xyz;
                return OUT;
            }
            
            half4 frag(VertexOutput IN) : SV_Target
            {
                UNITY_SETUP_INSTANCE_ID( IN );
                UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX( IN );

                float2 uv = IN.uv.xy;


                float4 color_vertex = IN.color;
                half3 ndc = IN.positionSS.xyz / (IN.positionSS.w  + 0.00000000001);
                half2 screenUV = ndc.xy;
                float time = _Time.y;
                
                float2 uv_MainTex_speed = (float2(_MainTexUSpeed , _MainTexVSpeed));
                float2 uv_MainTex = (_MainTexScreenUV ? screenUV : uv) * _MainTex_ST.xy + _MainTex_ST.zw;
                float2 uv_MainTex_offset = uv_MainTex + frac(time * uv_MainTex_speed);
                float2 uv_colorTex_speed = (float2(_ColorTexUSpeed , _ColorTexVSpeed));
                float2 uv_colorTex = (_ColorTexScreenUV ? screenUV : uv) * _ColorTex_ST.xy + _ColorTex_ST.zw;
                float2 uv_colorTex_offset = uv_colorTex + frac(time * uv_colorTex_speed);
                

                uv_MainTex_offset =  lerp(uv_MainTex_offset,clamp(uv_MainTex_offset,0,1.0),_MainTexClamp);
                half4 mainTex = tex2D(_MainTex,uv_MainTex_offset);
                half4 colorTex = tex2D(_ColorTex,uv_colorTex_offset);
                mainTex.rgb *= lerp(1, colorTex.rgb,_ColorTexIntensity);
                half4 mainColor =  _MainColor;
                half4 mainColor_final = ( mainColor * mainTex );

                


                half4 fresnel_color = half4(0,0,0,0);
                

                float3 worldNormal = IN.normalWS.xyz;
                float3 WorldPosition = IN.positionWS;
                half fresnelNdotV279 = 0;
                if(unity_OrthoParams.w>0)//当是正交相机时
                {
                    float3 normalView = mul((float3x3)UNITY_MATRIX_V, worldNormal).xyz;
                    fresnelNdotV279 = normalView.z;
                }
                else
                {
                    float3 worldViewDir = ( _WorldSpaceCameraPos.xyz - WorldPosition );
                    worldViewDir = normalize(worldViewDir);
                    fresnelNdotV279 = dot( worldNormal, worldViewDir );
                }

                
                
                half fresnelNode279 = ( 0.0 + _FnlScale * pow(abs(1.0 - fresnelNdotV279), _FnlPower));
                half temp_output_283_0 = saturate( fresnelNode279 );
                half4 FnlMainColor286 = ( _FnlColor * temp_output_283_0 * _FnlColor.a );
                
                
                fresnel_color = FnlMainColor286 ;
                
                

                float3 color_final =  color_vertex.rgb * lerp( mainColor_final.rgb ,mainColor_final.rgb + mainColor_final.rgb*fresnel_color.rgb,fresnel_color.a);
                
                

              
                

                half3 Color = color_final;
                half Alpha = mainColor_final.a;
                half4 finalColor = half4(Color, Alpha);
                finalColor = saturate(finalColor);
	            finalColor *= dt_ClipInWorldY(IN.positionWS.y);
	            return BloomOutfrag(finalColor);

            }
            ENDHLSL
        }
        
        Pass
        {
            ZWrite On
            ZTest LEqual
            Blend SrcAlpha OneMinusSrcAlpha
            
            // 第一个Pass使用轮廓线颜色渲染整个背面的面片
            NAME "Outline" 
            
            Tags 
            { 
                "RenderType"="Transparent" 
                "LightMode" = "ForwardBase"
                "Queue"="Transparent"
            }
            Cull Front 
            HLSLPROGRAM
            #pragma vertex vertOuline 
            #pragma fragment fragOuline


            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv0 : TEXCOORD0; 
                // float2 uv1 : TEXCOORD1;
                half3 normal : NORMAL;
                float4 color : COLOR;
            };

            struct v2f
            {
                float4 uv : TEXCOORD0;
                float4 color : COLOR;
                // half4 vertexColor : TEXCOORD1;
                half3 worldNormal : TEXCOORD2;
                float3 worldPos : TEXCOORD3;

                float4 positionHCS : SV_POSITION;
            };     
            v2f vertOuline(appdata v)
            {
                v2f o = (v2f)0;
                
                // float3 normalWS = UnityObjectToWorldDir(v.normal);
                // float3 normalHCS = normalize(mul((float3x3)UNITY_MATRIX_VP, normalWS).xyz);
                // normalHCS.xy = normalHCS.xy * _OutlineWidth * v.color.a;
                // float4 positionHCS = UnityObjectToClipPos(v.vertex.xyz);
                // positionHCS.xy += min(1.0 , positionHCS.w) * normalHCS.xy;
                // o.positionHCS = positionHCS;
                float3 positionWS = mul(unity_ObjectToWorld, float4(v.vertex.xyz, 1.0));

                float4 positionHCS = UnityWorldToClipPos(positionWS);
                float3 normalWS = normalize(mul((float3x3)UNITY_MATRIX_IT_MV, v.normal));
                normalWS = mul(UNITY_MATRIX_P, float4(normalWS,1)).xyz;
                normalWS.z = 0.001;
                normalWS = normalize(normalWS);

                float width = _OutlineWidth * v.color.a * 0.01;
                width *= positionHCS.w; // 距离修正

                positionHCS.xy += normalWS.xy * width;

                /// 相机Z轴内推
                half pushZ = v.color.a * 0.01 * _ZCorrection;
                half sign = 0;
            #if UNITY_REVERSED_Z
                sign = -1;//DX
            #else
                sign = 1;//OpenGL
            #endif
                positionHCS.z += sign * pushZ;
                o.positionHCS = positionHCS;
                
                
                o.worldPos =  positionWS;
                o.uv.xy = v.uv0;
                return o;
            }
            fixed4 fragOuline(v2f i) : SV_Target
            {
                fixed4 finalColor = _OutlineTint * tex2D(_MainTex,i.uv.xy);
                finalColor = saturate(finalColor);
	            finalColor *= dt_ClipInWorldY(i.worldPos.y);
                return finalColor;
            }
            ENDHLSL
        } 
        
    }	
    Fallback "Hidden/InternalErrorShader"
}
